<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage, ElMessageBox, type ComponentSize, type TabsPaneContext } from 'element-plus'
import { getJueSeWeiHuApi, addJueSeApi, getTreeApi } from '@/api/system'
import { onMounted } from 'vue'
import { Plus, Search } from '@element-plus/icons-vue'
import addJueSe from './components/addJueSe.vue'
import { empowerArry } from '../dictionary'
import { nextTick } from 'vue'
import { convertTreeChecked } from '@/utils/publicMethods'

const activeName = ref('JueSe')
const handleClick = (tab: TabsPaneContext) => {
  if (tab.props.name === 'JueSe') {
    getJueSeWeiHuFn()
  }
}

// 角色维护 ----------------------------------------------------------------------
const JueSeloading = ref(true)
const JueSeSize = ref<ComponentSize>('default')
const JueSeTotal = ref(0)
const JueSeTableData = ref([])
const JueSeWeiHuParams = ref({
  sqlId: 'roleMgr.getRoleInfo',
  pagination: true,
  page: 1,
  rows: 10
})
// 角色维护表格数据
const getJueSeWeiHuFn = async () => {
  JueSeloading.value = true
  // 调用接口获取数据
  await getJueSeWeiHuApi(JueSeWeiHuParams.value)
    .then((res: any) => {
      // console.log(res)
      JueSeTotal.value = res.total
      JueSeTableData.value = res.rows
      JueSeloading.value = false
    })
    .catch(() => {
      ElMessage({ message: '获取失败', type: 'error' })
    })
}
// 添加角色
const addJueSeRef = ref<any>()
const addJueSeBtn = () => {
  addJueSeRef.value.addJueSeVisible = true
}
// 删除角色
const deleteJueSeFn = async (itemInfo: any) => {
  const params = {
    sqlId: JSON.stringify([
      'roleMgr.deleteRole',
      'roleMgr.deleteUserRole',
      'roleMgr.deleteRoleMenu',
      'roleMgr.deleteAppRole',
      'roleMgr.deleteAppClsRole'
    ]),
    sqlParam: JSON.stringify([[itemInfo], [itemInfo], [itemInfo], [itemInfo], [itemInfo]]),
    dbName: undefined
  }
  await addJueSeApi(params)
    .then((res: any) => {
      if (res === 'success') {
        getJueSeWeiHuFn()
        ElMessage({ message: '删除成功', type: 'success' })
      } else {
        ElMessage({ message: '删除失败', type: 'error' })
      }
    })
    .catch(() => {
      ElMessage({ message: '删除失败', type: 'error' })
    })
}
const deleteJueSeBtn = (row: any) => {
  // console.log('删除角色', row)
  ElMessageBox.confirm('你确定要删除这个角色？', '删除角色', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(() => {
      deleteJueSeFn(row)
    })
    .catch(() => {
      ElMessage({ message: '已取消删除', type: 'info' })
    })
}

// 用户授权 ----------------------------------------------------------------------
const YongHuloading = ref(true)
const YongHuFrom = ref({
  roleId: 0,
  userName: '',
  roleFlag: -1,
  page: 1,
  rows: 10
})

const YongHuOptions = empowerArry
// 获取用户
const YongHuTableData = ref([])
const YongHuTotal = ref(0)
const multipleTableRef = ref<any>() // 表格ref
const multipleSelection = ref<any[]>([])
const authorizedArry = ref<any>([]) // 授权数组
const getYongHuDataFn = async () => {
  YongHuloading.value = true
  const params = {
    sqlId: 'roleMgr.getUserRole',
    sqlParam: JSON.stringify({
      roleId: YongHuFrom.value.roleId,
      userName: YongHuFrom.value.userName,
      roleFlag: String(YongHuFrom.value.roleFlag)
    }),
    pagination: true,
    page: YongHuFrom.value.page,
    rows: YongHuFrom.value.rows
  }
  YongHuTableData.value = []
  multipleSelection.value = []
  authorizedArry.value = []
  multipleTableRef.value.clearSelection()
  await getJueSeWeiHuApi(params)
    .then((res: any) => {
      // console.log(res)
      YongHuTotal.value = res.total
      YongHuTableData.value = res.rows
      YongHuTableData.value.forEach((item: any) => {
        if (item.checked === 1) {
          authorizedArry.value.push({
            user_id: item.user_id,
            role_id: YongHuFrom.value.roleId
          })
          multipleTableRef.value.toggleRowSelection(item, true)
        }
      })
      YongHuloading.value = false
    })
    .catch(() => {
      ElMessage({ message: '获取失败', type: 'error' })
    })
}
const handleSelectionChange = (val: any[]) => {
  multipleSelection.value = []
  multipleSelection.value = val
}

// 授权
const empowerFn = async () => {
  let addsqlParam = []
  let delsqlParam = []
  let sqlIdInfo = []
  let sqlParamInfo = []
  let sqlParam = []
  sqlParam = multipleSelection.value.map((item: any) => {
    return {
      user_id: item.user_id,
      role_id: YongHuFrom.value.roleId
    }
  })
  // console.log(multipleSelection.value, sqlParam, authorizedArry.value)

  addsqlParam = sqlParam.filter(
    (sqlItem: any) =>
      !authorizedArry.value.some(
        (authorizedItem: any) => authorizedItem.user_id === sqlItem.user_id
      )
  )
  delsqlParam = authorizedArry.value.filter(
    (authorizedItem: any) =>
      !sqlParam.some((sqlItem: any) => sqlItem.user_id === authorizedItem.user_id)
  )

  if (delsqlParam.length === 0 && addsqlParam.length === 0) {
    // console.log(addsqlParam, delsqlParam)
    ElMessage({ message: '请选择角色', type: 'error' })
    return
  }
  if (delsqlParam.length > 0) {
    sqlIdInfo.push('roleMgr.deleteUserRole')
    sqlParamInfo.push(delsqlParam)
  }
  if (addsqlParam.length > 0) {
    sqlIdInfo.push('roleMgr.insertUserRole')
    sqlParamInfo.push(addsqlParam)
  }
  const params = {
    sqlId: JSON.stringify(sqlIdInfo), // roleMgr.deleteUserRole
    sqlParam: JSON.stringify(sqlParamInfo)
  }
  // console.log(params)

  await addJueSeApi(params)
    .then((res: any) => {
      if (res === 'success') {
        getYongHuDataFn()
        ElMessage({ message: '授权成功', type: 'success' })
      } else {
        ElMessage({ message: '授权失败', type: 'error' })
      }
    })
    .catch(() => {
      ElMessage({ message: '授权失败', type: 'error' })
    })
}
// 授权
const empowerBtn = () => {
  empowerFn()
}

const YongHuClick = (row: any) => {
  // 角色ID
  YongHuFrom.value.roleId = row.role_id
  getYongHuDataFn()
  activeName.value = 'YongHu'
}

const YongHuSearchBtn = () => {
  getYongHuDataFn()
}

// 菜单授权 ----------------------------------------------------------------------
const CaiDanloading = ref(true)

interface Tree {
  children?: Tree[]
  id: number
  parent: number
  checked: boolean
  text: string
}
const CaiDanFrom = ref<any>({
  role_id: 10000
})

const caiDanTreeRef = ref<any>()
// 菜单树请求
const CaiDanTreeData = ref<Tree[]>([])
// 菜单树选中
const traverseAndSetChecked = (items: Tree[]) => {
  items.forEach((item: Tree) => {
    if (item.checked) {
      caiDanTreeRef.value.setChecked(item.id, true)
    }
    if (item.children && item.children.length > 0) {
      traverseAndSetChecked(item.children)
    }
  })
}
const getCaiDanTree = async () => {
  CaiDanloading.value = true
  CaiDanTreeData.value = []
  const params = {
    sqlId: 'roleMgr.getRoleMenu',
    sqlParam: JSON.stringify({ role_id: String(CaiDanFrom.value.role_id) }),
    id: 0,
    field: JSON.stringify({ id: 'menu_id', name: 'menu_name', parent: 'parent_id' })
  }
  await getTreeApi(params)
    .then((res: any) => {
      CaiDanTreeData.value = JSON.parse(JSON.stringify(convertTreeChecked(res)))
      nextTick(() => {
        traverseAndSetChecked(CaiDanTreeData.value) //基于最新的DOM状态执行update方法
        CaiDanloading.value = false
      })
    })
    .catch(() => {
      ElMessage({ message: '获取失败', type: 'error' })
    })
    .finally(() => {
      checkedKeys.value = []
    })
}

const CaiDanClick = (row: any) => {
  // 角色ID
  CaiDanFrom.value.role_id = row.role_id
  getCaiDanTree()
  activeName.value = 'CaiDan'
}
// 选中数组
const checkedKeys = ref<string[]>([])
// 菜单授权保存
const CaiDanSaveBtn = () => {
  const info = checkedKeys.value.map((item) => {
    return {
      role_id: CaiDanFrom.value.role_id,
      menu_id: item
    }
  })
  const params = {
    sqlId: JSON.stringify(['roleMgr.deleteRoleMenu', 'roleMgr.insertRoleMenu']),
    sqlParam: JSON.stringify([{ role_id: CaiDanFrom.value.role_id }, [...info]])
  }
  addJueSeApi(params)
    .then((res: any) => {
      if (res === 'success') {
        getCaiDanTree()
        ElMessage({ message: '保存成功', type: 'success' })
      } else {
        ElMessage({ message: '保存失败', type: 'error' })
      }
    })
    .catch(() => {
      ElMessage({ message: '操作失败', type: 'error' })
    })
}

// 应用授权 ----------------------------------------------------------------------
const YingYongTree = (tree: any) => {
  return tree.map((node: any) => {
    const convertedNode = {
      attributes: node.attributes ? node.attributes : undefined,
      checked: node.checked,
      children: node.children ? convertTreeChecked(node.children) : undefined,
      id: node.id,
      parent: node.parent,
      state: node.state,
      label: node.text
    }
    return convertedNode
  })
}
const YingYongInfo = ref<any>({ role_id: 10000 })
// 获取应用授权数据
const YingYongHeight = window.innerHeight - 300
const YingYongloading = ref<boolean>(false)
const YingYongData = ref<any>([])
const YingYongTreeRef = ref<any>()
const YingYongcheckedKeys = ref<string[]>([])
// 菜单树选中
const YingYongSetChecked = (items: Tree[]) => {
  items.forEach((item: Tree) => {
    if (item.checked) {
      YingYongTreeRef.value.setCheckedKeys([item.id])
    }
    if (item.children && item.children.length > 0) {
      YingYongSetChecked(item.children)
    }
  })
}
const getYingYongDataFn = async () => {
  YingYongData.value = []
  YingYongloading.value = true
  const params = {
    sqlId: 'roleMgr.appRoleRight',
    sqlParam: JSON.stringify({ role_id: String(YingYongInfo.value.role_id) }),
    id: 'cls0'
  }
  await getTreeApi(params)
    .then((res: any) => {
      YingYongData.value = JSON.parse(JSON.stringify(YingYongTree(res)))
      nextTick(() => {
        YingYongSetChecked(YingYongData.value) //基于最新的DOM状态执行update方法
        YingYongloading.value = false
      })
    })
    .catch(() => {
      ElMessage({ message: '获取失败', type: 'error' })
    })
    .finally(() => {
      YingYongcheckedKeys.value = []
    })
}

const YingYongSaveBtn = () => {
  let clsArry = []
  let rootNodeArry = []
  clsArry = YingYongcheckedKeys.value.filter((item) => item.includes('cls'))
  rootNodeArry = YingYongcheckedKeys.value.filter((item) => !item.includes('cls'))
  clsArry = clsArry.map((item: any) => {
    return {
      role_id: YingYongInfo.value.role_id,
      class_id: item.replace('cls', '')
    }
  })
  rootNodeArry = rootNodeArry.map((item: any) => {
    return {
      role_id: YingYongInfo.value.role_id,
      app_id: item.split(',')[0],
      class_id: item.split(',')[1]
    }
  })
  // console.log(clsArry, rootNodeArry)
  const params = {
    sqlId:
      YingYongcheckedKeys.value.length > 0
        ? JSON.stringify([
            'roleMgr.deleteAppRole',
            'roleMgr.deleteAppClsRole',
            'roleMgr.insertAppRole',
            'roleMgr.insertAppClsRole'
          ])
        : JSON.stringify(['roleMgr.deleteAppRole', 'roleMgr.deleteAppClsRole']),
    sqlParam:
      YingYongcheckedKeys.value.length > 0
        ? JSON.stringify([
            { role_id: YingYongInfo.value.role_id },
            { role_id: YingYongInfo.value.role_id },
            [...rootNodeArry],
            [...clsArry]
          ])
        : JSON.stringify([
            { role_id: YingYongInfo.value.role_id },
            { role_id: YingYongInfo.value.role_id }
          ])
  }
  addJueSeApi(params)
    .then((res: any) => {
      if (res === 'success') {
        getYingYongDataFn()
        ElMessage({ message: '保存成功', type: 'success' })
      } else {
        ElMessage({ message: '保存失败', type: 'error' })
      }
    })
    .catch(() => {
      ElMessage({ message: '操作失败', type: 'error' })
    })
}

const YingYongClick = (row: any) => {
  YingYongInfo.value.role_id = row.role_id
  getYingYongDataFn()
  activeName.value = 'YingYong'
}
// 公共 ----------------------------------------------------------------------
const handleCheckChange = (data: any, checked: any) => {
  // console.log(data, checked)
  if (activeName.value === 'CaiDan') {
    checkedKeys.value = checked.halfCheckedKeys.concat(checked.checkedKeys)
  }
  if (activeName.value === 'YingYong') {
    YingYongcheckedKeys.value = checked.halfCheckedKeys.concat(checked.checkedKeys)
  }
}

const handleSizeChange = (val: number) => {
  if (activeName.value === 'JueSe') {
    JueSeWeiHuParams.value.page = 1
    JueSeWeiHuParams.value.rows = val
    getJueSeWeiHuFn()
  }
  if (activeName.value === 'YongHu') {
    YongHuFrom.value.page = 1
    YongHuFrom.value.rows = val
    getYongHuDataFn()
  }
}

const handleCurrentChange = (val: number) => {
  if (activeName.value === 'JueSe') {
    JueSeWeiHuParams.value.page = val
    getJueSeWeiHuFn()
  }
  if (activeName.value === 'YongHu') {
    YongHuFrom.value.page = val
    getYongHuDataFn()
  }
}

onMounted(() => {
  getJueSeWeiHuFn()
})
</script>
<template>
  <div class="JueSeGuanLiBox">
    <el-tabs v-model="activeName" type="card" class="JueSeTabs" @tab-click="handleClick">
      <el-tab-pane class="JueSeWeiHu" label="角色维护" name="JueSe">
        <div id="actionBox">
          <el-button
            type="success"
            :disabled="JueSeloading"
            plain
            :icon="Plus"
            @click="addJueSeBtn"
          >
            添加
          </el-button>
        </div>
        <el-table
          v-loading="JueSeloading"
          class="JueSeWeiHuTable"
          :data="JueSeTableData"
          stripe
          border
          style="width: 100%"
        >
          <el-table-column prop="role_id" label="角色ID" width="180" />
          <el-table-column prop="role_name" label="角色名称" width="240" />
          <el-table-column prop="remark" label="角色描述" />
          <el-table-column label="授权" width="280">
            <template #default="scope">
              <el-button text type="primary" @click="YongHuClick(scope.row)"> 用户授权 </el-button>
              <el-button text type="primary" @click="CaiDanClick(scope.row)"> 菜单授权 </el-button>
              <el-button text type="primary" @click="YingYongClick(scope.row)">
                应用授权
              </el-button>
              <el-button type="danger" text @click="deleteJueSeBtn(scope.row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination
          class="paginationBox"
          v-model:current-page="JueSeWeiHuParams.page"
          v-model:page-size="JueSeWeiHuParams.rows"
          :page-sizes="[10, 20, 30, 40]"
          :size="JueSeSize"
          :disabled="false"
          :background="true"
          layout="total, sizes, prev, pager, next, jumper"
          :total="JueSeTotal"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        >
        </el-pagination>
      </el-tab-pane>
      <el-tab-pane
        class="YongHuShouQuan"
        label="用户授权"
        :disabled="activeName !== 'YongHu'"
        name="YongHu"
      >
        <div id="actionBox">
          <el-form :inline="true" :model="YongHuFrom" class="demo-form-inline">
            <el-form-item label="用户名：">
              <el-input v-model="YongHuFrom.userName" placeholder="请输入用户名" />
            </el-form-item>
            <el-form-item label="授权类型：">
              <el-select
                v-model="YongHuFrom.roleFlag"
                placeholder="请选择授权类型"
                style="width: 120px"
              >
                <el-option
                  v-for="item in YongHuOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" :icon="Search" @click="YongHuSearchBtn">查询</el-button>
              <el-button
                :disabled="YongHuloading"
                type="success"
                plain
                :icon="Plus"
                @click="empowerBtn"
                >添加授权</el-button
              >
            </el-form-item>
          </el-form>
          <el-table
            v-loading="YongHuloading"
            ref="multipleTableRef"
            class="YongHuShouQuanTable"
            :data="YongHuTableData"
            stripe
            border
            :row-key="(row: any) => row.user_id"
            style="width: 100%"
            @selection-change="handleSelectionChange"
          >
            <el-table-column type="selection" :reserve-selection="true" width="40" />
            <el-table-column prop="user_id" label="用户ID" width="140" />
            <el-table-column prop="user_name" label="用户名" width="240" />
            <el-table-column prop="region_name" label="地域" />
          </el-table>
          <el-pagination
            class="paginationBox"
            v-model:current-page="YongHuFrom.page"
            v-model:page-size="YongHuFrom.rows"
            :page-sizes="[10, 20, 30, 40]"
            :size="JueSeSize"
            :disabled="false"
            :background="true"
            layout="total, sizes, prev, pager, next, jumper"
            :total="YongHuTotal"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          ></el-pagination>
        </div>
      </el-tab-pane>
      <el-tab-pane label="菜单授权" :disabled="activeName !== 'CaiDan'" name="CaiDan">
        <div id="actionBox">
          <el-button
            :disabled="CaiDanloading"
            type="success"
            plain
            :icon="Plus"
            @click="CaiDanSaveBtn"
            >添加授权</el-button
          >
        </div>
        <el-tree
          v-if="activeName === 'CaiDan'"
          v-loading="CaiDanloading"
          ref="caiDanTreeRef"
          class="treeBox"
          style="max-width: 100%"
          :data="CaiDanTreeData"
          node-key="id"
          show-checkbox
          :default-expand-all="true"
          :expand-on-click-node="false"
          @check="handleCheckChange"
        >
        </el-tree>
      </el-tab-pane>
      <el-tab-pane label="应用授权" :disabled="activeName !== 'YingYong'" name="YingYong">
        <div id="actionBox">
          <el-button
            :disabled="YingYongloading"
            type="success"
            plain
            :icon="Plus"
            @click="YingYongSaveBtn"
            >添加授权</el-button
          >
        </div>
        <el-tree-v2
          v-if="activeName === 'YingYong'"
          v-loading="YingYongloading"
          ref="YingYongTreeRef"
          class="YingYongTreeBox"
          style="max-width: 100%"
          :height="YingYongHeight"
          :data="YingYongData"
          node-key="id"
          show-checkbox
          :expand-on-click-node="false"
          @check="handleCheckChange"
        >
        </el-tree-v2>
      </el-tab-pane>
    </el-tabs>
    <addJueSe ref="addJueSeRef" @getJueSeWeiHuFn="getJueSeWeiHuFn" />
  </div>
</template>
<style scoped lang="less">
#actionBox {
  padding: 0 8px;
  margin-bottom: 15px;
  .el-button {
    padding: 0 16px;
  }
}
.JueSeGuanLiBox {
  position: relative;
  // padding-top: 4px;
  height: calc(100vh - 150px);
  .JueSeWeiHu {
    padding: 0 8px;
    .el-button {
      padding: 0;
    }
    .JueSeWeiHuTable {
      height: calc(100vh - 300px);
    }
    .paginationBox {
      position: fixed;
      bottom: 20px;
    }
  }
  .YongHuShouQuan {
    padding: 0 8px;
    .YongHuShouQuanTable {
      height: calc(100vh - 300px);
    }
    .paginationBox {
      position: fixed;
      bottom: 20px;
    }
  }
  .YingYongTreeBox {
    height: calc(100vh - 150px);
  }
  :deep(.el-tabs__header) {
    .el-tabs__nav {
      border-top: unset;
      border-left: unset;
      border-radius: 0;
    }
  }
}
</style>
